<template>
  <div style="width: 100%">
    <span v-if="props.showText">{{currValue || ''}}</span>
    <span v-else :class="['cc-input-number', $slots.append ? 'append' : '']">
      <el-input-number
        v-model="currValue"
        :placeholder="calcPlaceholder"
        :controls="true"
        controls-position="right"
        :step="precision === 1 ? 0.1 : precision === 2 ? 0.01 : 1"
        :precision="precision"
        :min="min"
        :max="max"
        :disabled="disabled"
        :readonly="readonly"
        @input="handleInput"
        @change="handleChange"
        @blur="handleBlur"
      >
        <template #prefix v-if="prefixText">
          <span>{{prefixText}}</span>
        </template>
        <template #suffix v-if="suffixText">
          <span>{{suffixText}}</span>
        </template>
      </el-input-number>
      <span class="cc-input-number-append" v-if="$slots.append">
        <slot name="append" />
      </span>
    </span>
  </div>
</template>

<script setup>
import { onBeforeMount, ref, watch, inject, nextTick, computed } from 'vue';
import { useDisabled } from 'element-plus';

const emit = defineEmits(['update:modelValue', 'change', 'blur']);
const props = defineProps({
  prop: {
    type: String,
    default: ''
  },
  point: {
    type: [String, Number],
    default: 0
  },
  min: {
    type: Number,
    default: -Infinity
  },
  max: {
    type: Number,
    default: Infinity
  },
  prefixText: String,
  suffixText: String,
  placeholder: String,
  showText: Boolean,
  disabled: Boolean,
  readonly: Boolean,
});
const formData = inject('formData');

const currValue = ref(0);
const min = ref(null);
const max = ref(2147483647);
const precision = ref(parseInt((props.point || '0')));
const disabled = ref(false);
const readonly = ref(false);
const inputDisabled = useDisabled();

const init = (data) => {
  min.value = data.min || min.value;
  max.value = data.max || max.value;
  precision.value = parseInt((data.point || '0'));
  disabled.value = inputDisabled.value || data.disabled || false;
  readonly.value = data.readonly || false;
};

const handleInput = (value) => {
  currValue.value = formatter(value);
  formData.value[props.prop] = currValue.value;
  nextTick(() => emit('change'));
};

const handleChange = () => {
  formData.value[props.prop] = currValue.value;
  nextTick(() => emit('change'));
};

const handleBlur = () => {
  formData.value[props.prop] = currValue.value;
  emit('change');
  emit('blur');
};

const formatter = (value) => {
  return value ? parseFloat(value.toFixed(precision.value)) : undefined;
}

const calcPlaceholder = computed(() => {
  return disabled.value === true ? '' : props.placeholder;
});

watch(() => props, (data) => {
  init(data);
}, {immediate: true, deep: 1});

watch(() => formData.value[props.prop], (data) => {
  if (data === null || data === '') {
    currValue.value = null;
  }
  if (precision.value > 0) {
    currValue.value = parseFloat(data);
  } else {
    currValue.value = parseInt(data);
  }
}, {immediate: true});

onBeforeMount(() => {
  init(props);
});
</script>

<style scoped>
.cc-input-number {
  display: flex;
  flex-direction: row;
  width: 100%;
}
.cc-input-number :deep(.el-input-number) {
  width: 100%;
}
.cc-input-number :deep(.el-input-number--small) {
  padding: 0;
  text-align: left;
  width: 100%;
}
.cc-input-number :deep(.el-input-number .el-input__inner) {
  text-align: left;
}
.cc-input-number.append :deep(.el-input__wrapper) {
  border-top-right-radius: 0!important;
  border-bottom-right-radius: 0!important;
}
.cc-input-number :deep(.cc-input-number-append) {
  background-color: #f5f7fa;
  color: #909399;
  border: 1px solid #dcdfe6;
  border-left: none;
  border-top-right-radius: 4px;
  border-bottom-right-radius: 4px;
  padding: 0 10px;
  white-space: nowrap;
  height: 30px;
  line-height: 30px;
}
</style>